import React, { useState, useEffect } from 'react';

/*
class FriendStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  handleStatusChange(status) {
    this.setState({
      isOnline: status.isOnline
    });
  }

  render() {
    if (this.state.isOnline === null) {
      return 'Loading...';
    }
    return this.state.isOnline ? 'Online' : 'Offline';
  }
}


function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // Specify how to clean up after this effect:
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
*/

function Counter(){
  const [state, setState] = useState({number: 0});

  //useEffect里的函数会在组件挂载完成后,或则组件更新完成后进行调用
  /*
    如果没有给第二个参数 ↑函数会在每次执行渲染后调用
    而如果是空数组 则只会在组件挂载完成执行一次后就不再执行了
  */
  useEffect(() => {
    //@ts-ignore
    // document.title = state.number // 这一行就等于上面被注释的两个生命周期(componentDidMount、componentDidUpdate)里执行该函数

    console.log('开始一个定时器');
    //↓注意如果依赖的不是空数组 定时器就可能被叠加执行
    const timer = setInterval(() => {
      setState(x => ({number: x.number + 1}))
    }, 1000);

    //useEffect会返回一个清理函数,当组件将要卸载的时候会执行清理函数
    //如果不使用useEffect的第二个参数(即deps中我们不设置`[]`)
    //则每次Counter函数调用时 都会先执行↓下面return的函数 (除了组件刚mounted时)
    //然后再执行useEffect的函数
    // (意思是每次渲染都会先销毁上一个设置的定时器,然后再开启一个新的定时器,console里我们可以看到会先打印 '销毁一个定时器' 然后跟着打印 '开始一个定时器')
    //没错这种情况会先执行return的函数 然后才会执行回调
    //另外↓这个函数 也会在组件销毁时单独执行
    return () => {
      console.log('销毁一个定时器');
      clearInterval(timer);
    };
  });

  return (
    <div>
      <p>{state.number}</p>
      <button onClick={() => setState({number: state.number + 1})}>+</button>
    </div>
  );
}

export default function App(){
  const [visible, setVisible] = useState(true);
  //点击会销毁Counter
  return (
    <div>
      <button onClick={()=>setVisible(false)}>hide</button>
      {visible && <Counter/>}
    </div>
  )
}


/** 清除时机伪代码↓↓ https://reactjs.org/docs/hooks-effect.html
// Mount with { friend: { id: 100 } } props
ChatAPI.subscribeToFriendStatus(100, handleStatusChange);     // Run first effect

// Update with { friend: { id: 200 } } props
ChatAPI.unsubscribeFromFriendStatus(100, handleStatusChange); // Clean up previous effect
ChatAPI.subscribeToFriendStatus(200, handleStatusChange);     // Run next effect

// Update with { friend: { id: 300 } } props
ChatAPI.unsubscribeFromFriendStatus(200, handleStatusChange); // Clean up previous effect
ChatAPI.subscribeToFriendStatus(300, handleStatusChange);     // Run next effect

// Unmount
ChatAPI.unsubscribeFromFriendStatus(300, handleStatusChange); // Clean up last effect
*/
